Repository navigation
fix: give each agent space its own LaunchDarkly MCP server - #968
Merged
Merged
Conversation
Setup found the LaunchDarkly MCP server by its endpoint and reused it for every agent space in the account and region. All spaces then used the token of the first run, and a token replacement changed the token of every space. Setup now finds the server of a space by its association. A space with no server gets a new server named "LaunchDarkly <agent-space-id>". With --replace-mcp-token, only the chosen space changes. If other spaces use the old server, they keep it and its token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7be840b. Configure here.
AWS allows only letters, digits, "_" and "-" in an MCP server name, so the server of a space is now named "LaunchDarkly-<agent-space-id>". A replace on a shared server removes the new server if the old server cannot be disconnected, so the space stays as it was. A run after a failure removes an unused server with the name of the space before it registers the new one. A replace on a server that only this space uses keeps the name of the server, as the plan says. The plan now warns when a reused server is shared with other spaces. Setup stops if a space is connected to more than one LaunchDarkly server, or if --mcp-service-id names a server other than the server of the space. The check before the MCP step uses the ID of a new space. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A replace now always names the new server LaunchDarkly-<agent-space-id>, and the plan says when this renames the server. Before, a replace on an unshared server kept the old name, so a run after a failed association could not find the new server, and it stayed behind with a live token. A replace stops at plan time when the shared server already has the name of the space. The new server cannot have that name, so every run failed on the name. The error tells the user to move the other spaces to their own servers first. After a failed disconnect, setup checks the association again before it says which server the space uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A replace now removes an unused server with the name of the space on an unshared server too, and the plan says so. Before, the registration failed on the name after setup had already removed the old server, so the space had no server. After a failed disconnect from a shared server, setup checks the association before it removes the new server. If AWS made the disconnect, the run keeps the new server and connects it. The error for a server that has the name of the space now offers a rename in the AWS console first. It names the other agent spaces and shows how to choose each one with --agent-space-id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 of 3 tasks
erangeles
approved these changes
Oct 26, 2026
cchu-ld
added a commit
that referenced
this pull request
Oct 27, 2026
Since #968, setup registers a server for each agent space, named LaunchDarkly-<agent space ID>, and a replace can rename a server. The agent's tool IDs used the fixed name LaunchDarkly, so they would not match. The run now reads the name of the registered server, and the plan shows the name that the server will have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cchu-ld
added a commit
that referenced
this pull request
Oct 27, 2026
Since #968, setup registers a server for each agent space, named LaunchDarkly-<agent space ID>, and a customer can rename a server. Some plan lines and log messages still said "MCP server LaunchDarkly": - The skip and ask plan lines, and the skip log, now say "the MCP server of this agent space", like the register line. - The association logs name the server that setup reused or registered. - The warning about a server that appeared after the first plan falls back to the name of the server of the space. - The comments on MCPStep.name and MCPStep.Name say which name each one is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cchu-ld
added a commit
that referenced
this pull request
Oct 27, 2026
…sages (#978) * feat: show the aws-devops-agent command in the help This reverts the code part of #958. Cobra shows the command in the help again, and the root usage listing names it. The README section stays out, because the behavior changed after #958. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name the MCP server of the agent space in setup messages Since #968, setup registers a server for each agent space, named LaunchDarkly-<agent space ID>, and a customer can rename a server. Some plan lines and log messages still said "MCP server LaunchDarkly": - The skip and ask plan lines, and the skip log, now say "the MCP server of this agent space", like the register line. - The association logs name the server that setup reused or registered. - The warning about a server that appeared after the first plan falls back to the name of the server of the space. - The comments on MCPStep.name and MCPStep.Name say which name each one is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name a server without a name by its ID in the second-plan warning The warning fell back to MCPServerNameFor of the space when AWS sent no name. That is the name that a run would register, not a name of the server that appeared, and the plan text names the same server another way. The warning now gives only the server ID, which identifies the server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2 of 3 tasks
cchu-ld
added a commit
that referenced
this pull request
Oct 27, 2026
…me (#979) * fix: shorten the MCP server name so every tool fits in 64 characters AWS caps an MCP server name, "_" and a tool name at 64 characters. The name from #968 holds the full space UUID (49 characters), so registration failed for 18 of the 31 allowlisted tools. Keep the first 13 characters of the space ID, and test that every allowlisted tool fits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the last 12 characters of the space ID in the MCP server name The last group of a UUID space ID has no dash, so the name reads as LaunchDarkly-97503e355157. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
cchu-ld
added a commit
that referenced
this pull request
Oct 28, 2026
Since #968, setup registers a server for each agent space, named LaunchDarkly-<agent space ID>, and a replace can rename a server. The agent's tool IDs used the fixed name LaunchDarkly, so they would not match. The run now reads the name of the registered server, and the plan shows the name that the server will have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cchu-ld
added a commit
that referenced
this pull request
Oct 29, 2026
…t setup (#972) * feat: add the experimentation skill to the agent space in setup Setup now adds the experiment-orchestration skill to the agent space. The skill tells the agent how to move a goal through an experiment, a guarded rollout, and a report. The skill text comes from the setup guide. If the space has a skill with the same name and other instructions, setup does not change it. Pass --replace-skill to replace the instructions. The status and agent types of the skill stay the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: make the skill step optional and update copies from older versions Setup now does the skill step after the MCP server step. If the skill step fails, setup shows a warning and puts the error in skillError. The other steps still run. If setup cannot read the skills of the space, the plan skips the skill. Setup keeps the SHA-256 of each SKILL.md that it sent. If a space has one of these texts, setup updates it without --replace-skill. Other text is a customer edit. The plan keeps the version of the skill asset. If the version changes before the write, setup does not change the skill. The plan line and the help text say that every agent type in the space can load the skill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the AWS message in skill warnings and report the skill action The skill warning now keeps the full AWS error, so it names the denied action. If AWS denies access, the warning also names the permissions that the skill step needs. The warning shows one time, at the end of the run. An empty SKILL.md now gets an update without --replace-skill. A skill with no SKILL.md gets its own plan line. A SKILL.md that AWS sends as bytes is compared as text. The setup result now has skillAction, so a JSON run shows if setup kept, updated, or left the skill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: report a plan change as a skipped skill and warn on stderr in JSON runs If the skill changes between the plan and the write, skillAction is now skipped, because setup tried no write. The warning for a denied GetAssetFile now names the skill one time. The plan line for a skipped skill starts with "Skip skill". A JSON run now also writes the skill warning to stderr. If someone deletes the skill after the list, the plan now creates a new skill. Before, the plan said that the skill had no SKILL.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: let the experiment skill resume across runs and wait 2 weeks for a result A scheduled run of the agent has no memory of the run that started the experiment. The skill now keeps an experiment record, tags the flags that it owns, and resumes in-flight work before it starts a new goal. The experiment now runs at least 2 weeks before a decision, not 30 minutes. A result that is not a win stops the iteration with control as the winner and turns the flag off. Guarded rollout stages stay at or below 50%, as LaunchDarkly requires. If no coding agent is available, the skill waits for a person to confirm the deployment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: shape the experiment skill for a chat run with approved writes In AWS DevOps Agent, every LaunchDarkly write needs a person to approve it in chat, and no coding agent or CI/CD is connected. The skill now runs as two chats: one that starts an experiment and one that checks on experiments. A person implements and deploys the change, and the agent stops at each wait. - The flag serves false when it is on, so turning it on before the experiment starts does not give everyone the treatment. - The experiment uses 10% of traffic through 5% and 5% treatments and notInExperimentVariationId, with sequential testing. - The agent shows the draft experiment and waits for a confirmation before it starts it, as the create-experiment tool asks. - The record in the flag description holds the project and environment. - The release review, merge, and deploy steps are gone. The allowlist adds update-flag-settings, for the record, and create-metric. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: add missing MCP tools to an existing allowlist on request, and keep the win out of the 100% path Stopping an experiment iteration serves the chosen winner to everyone that the rule matches. The skill now stops a won experiment with control as the winner, records the win first, makes sure that the default rule serves control, and then ramps the treatment with the guarded rollout. A space that reuses an MCP server kept its old allowlist, so the tools that the skill now uses were missing. Setup now names the missing tools in the plan and warns. With --add-mcp-tools it adds them. It rewrites the allowlist only if every tool on it is an ldcli tool, because AWS replaces the whole configuration and does not send back each tool's classification, and an unclassified tool runs without approval. The run skips the rewrite if the allowlist changed after the plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address review feedback on the experiment skill - The report template is in a fenced markdown block, so its headings stay out of the skill's outline. - The report compares control with treatment, not before with after. - "Design waiting for confirmation" is a record state, so a later chat resumes the draft experiment instead of making another one. - The skill says why the 2-week minimum holds with sequential testing on: sequential testing lets a guardrail regression end the experiment early, and the minimum covers weekly cycles and novelty effects. - The report recommends a flag cleanup for a winner too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: add the experiment-orchestrator custom agent to the agent space in setup Setup now creates a custom agent that runs the experiment-orchestration skill with the LaunchDarkly MCP tools that the space allows. The tool IDs are "<server name>_<tool name>", the format that AWS uses for a custom agent made in the console. An update adds the ldcli tools and skill to the agent and keeps the ones that the customer added. If someone edited the prompt, setup leaves the agent unless --replace-agent is passed. The agent is optional: if its step fails, or the MCP server or the skill is missing, setup warns and does the other steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: show the skill and the custom agent in status status now reports the experiment-orchestration skill and the experiment-orchestrator custom agent of each agent space: whether each is the ldcli version, an older one that setup updates, edited, without its file, or missing. For the agent, it also gives the number of tools and whether the skill is attached. An agent with the ldcli prompt but without the skill or an allowed tool is outdated, because setup updates it. Like the operator app, an asset that status cannot read does not stop it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: shape the custom agent prompt for chat runs and read-only runs The skill now runs in chat, where a person approves each write. Outside chat, for example in a scheduled run, every write fails. In chat, the agent follows the skill. Outside chat, it only reads: it reports, for each experiment in flight, what is due and the message to send in chat, and it never writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name the custom agent's tools after the server's name in AWS Since #968, setup registers a server for each agent space, named LaunchDarkly-<agent space ID>, and a replace can rename a server. The agent's tool IDs used the fixed name LaunchDarkly, so they would not match. The run now reads the name of the registered server, and the plan shows the name that the server will have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: add the experiment-orchestrator custom agent to the agent space in setup Setup now creates a custom agent that runs the experiment-orchestration skill with the LaunchDarkly MCP tools that the space allows. The tool IDs are "<server name>_<tool name>", the format that AWS uses for a custom agent made in the console. An update adds the ldcli tools and skill to the agent and keeps the ones that the customer added. If someone edited the prompt, setup leaves the agent unless --replace-agent is passed. The agent is optional: if its step fails, or the MCP server or the skill is missing, setup warns and does the other steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: show the skill and the custom agent in status status now reports the experiment-orchestration skill and the experiment-orchestrator custom agent of each agent space: whether each is the ldcli version, an older one that setup updates, edited, without its file, or missing. For the agent, it also gives the number of tools and whether the skill is attached. An agent with the ldcli prompt but without the skill or an allowed tool is outdated, because setup updates it. Like the operator app, an asset that status cannot read does not stop it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: shape the custom agent prompt for chat runs and read-only runs The skill now runs in chat, where a person approves each write. Outside chat, for example in a scheduled run, every write fails. In chat, the agent follows the skill. Outside chat, it only reads: it reports, for each experiment in flight, what is due and the message to send in chat, and it never writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name the custom agent's tools after the server's name in AWS Since #968, setup registers a server for each agent space, named LaunchDarkly-<agent space ID>, and a replace can rename a server. The agent's tool IDs used the fixed name LaunchDarkly, so they would not match. The run now reads the name of the registered server, and the plan shows the name that the server will have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: make the custom agent prompt a thin layer on the experiment skill The prompt now loads the experiment-orchestration skill from #970 and follows it as is. It adds only the LaunchDarkly MCP tools and one rule: never start a goal that a person did not ask for. The old prompt never shipped, so its hash is replaced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: shorten the custom agent prompt to one paragraph The prompt now has one paragraph that loads the experiment-orchestration skill and follows it. The help text for the custom agent is shorter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: remove --replace-agent from aws-devops-agent setup Setup never overwrites an edited prompt of the custom agent. The plan and the log say that setup leaves the agent, and that a person can delete the agent in the AWS console and run setup again to get the ldcli version. Status no longer names a flag for an edited agent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: leave the skill and the custom agent out of status Status does not show the experiment-orchestration skill or the experiment-orchestrator custom agent. Status is the same as on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: remove comments that repeat the code The comments that stay give a reason that the code does not show. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: remove dead code from the custom agent step Setup always connects the MCP server before the agent step, so the check for a missing server is gone. planAgent no longer takes the options, and the unused AllowedTools test helper is gone. The message for a missing permission now names aidevops:ListAssociations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: pass the MCP server name to the custom agent step The MCP step knows the name of the server, so it keeps the name in the result. The agent step no longer lists the servers again, and the OAuth poll test is the same as on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: give the custom agent the tools that --add-mcp-tools adds The plan compared the agent with the allowlist before the MCP step. With --add-mcp-tools, the MCP step adds tools first, so the plan kept the agent without them. The plan now expects those tools, so setup updates the agent in the same run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: sync the AWS DevOps Agent files from ai-tooling at a fixed commit The experiment-orchestration skill and the custom agent prompt now come from launchdarkly/ai-tooling. scripts/sync-aws-devops-agent.sh downloads them at the commit in AI_TOOLING_COMMIT. go generate and make aws-devops-agent-sync run it. ldcli embeds the files, so they stay committed. CI fails if they differ from that commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: sync the AWS DevOps Agent files from the ai-tooling merge commit The sync now pins 887d4cb, the merge commit of launchdarkly/ai-tooling#230. SKILL.md changed, so its hash is in shippedSkillHashes. The agent prompt did not change. The skill test now compares the description with the front matter of the embedded SKILL.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: say that setting up the skill and the custom agent is optional "The agent is optional" can mean that a space does not need the agent. The help text now says that the setup step is optional. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: allow the MCP tools of the whole experiment flow, and add them to existing spaces The allowlist now has the tools that the new SKILL.md names and that were missing: list-metric-events and update-off-variation. It also has tools for the rest of that work that the skill does not name: update-experiment, save-and-start-experiment-iteration, create-automated-rollout-config, get-flag-health, get-flag-unique-context-exposures, and search-contexts. Setup now adds the missing ldcli tools to the allowlist of an existing space without --add-mcp-tools, so spaces from older ldcli versions get the new tools. The flag still parses, has no effect, and is deprecated. A new test fails when SKILL.md names a tool that the allowlist does not have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: download the AWS DevOps Agent skill and prompt from ai-tooling main Setup no longer embeds SKILL.md and the custom agent prompt. The plan downloads both from the main branch of launchdarkly/ai-tooling, and the run writes the texts that the plan compared. If the download fails, setup skips the skill and custom agent steps and warns. A space text counts as ours when it is empty, matches a frozen hash of a released ldcli, or equals an earlier version of the file on ai-tooling main. Setup reads that history only when nothing else matches, and skips the step if it cannot read it. The plan and the result warn when the skill names MCP tools that this ldcli version does not allow. The sync and check scripts, their Makefile targets, and the CI step are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: drop the unknown-tool warning and the ai-tooling history check A future GitHub Action will compare the skill on ai-tooling main with the allowlist and open a pull request when they differ, so setup no longer warns about tools that the skill names. Setup also no longer reads the history of the files on ai-tooling main. A space whose text is the current main text or a text that a released ldcli embedded gets the new text. Other text counts as an edit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: skip an existing skill or agent that differs from ai-tooling main Setup no longer keeps the hashes of the texts that older ldcli versions embedded. If the skill in the space is not the latest SKILL.md on ai-tooling main, the plan says so and setup skips it. --replace-skill updates it to the latest version. A custom agent whose prompt differs is skipped the same way, with the hint to delete it and run setup again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: trim comments and dead code in the skill and custom agent steps Sources.File drops the ref, which is always main, and GitHubSources drops the nil-client fallback. planSkill is one function again, and skillText is inlined. Comments that repeat the code, or that describe the embedded files and the hash lists, are gone. The allowlist comment no longer says that the skill keeps its record in the flag description. Tests named for edits are named for a different text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: clarify why setup downloads the skill and prompt once Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: restore comments that the earlier cleanup only rephrased Comments whose code did not change get their wording from main back, and skillText and two test names return. Comments now change only where the behavior did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
ldcli aws-devops-agent setupre-used the same MCP server across agent spaces in a region - this also means re-using the same LD access token across teams, which isn't ideal.Change
LaunchDarkly-<agent-space-id>. If an earlier run registered the server but did not connect it, the next run finds the server by this name.--replace-mcp-token, only the chosen space changes:--mcp-service-idstill connects a server that the user chooses. Setup stops if the space already uses a different LaunchDarkly server, so a space never gets two.The help text of
setup,--replace-mcp-token,--mcp-service-id, and--mcp-endpointnow describes this behavior.Testing
go test ./...passes.golangci-lintreports 0 issues forcmd/aws_devops_agentandinternal/awsdevops.🤖 Generated with Claude Code
Note
Overview
Setup no longer picks a single account-wide LaunchDarkly MCP server by endpoint. It resolves MCP state per agent space via associations, registers new servers as
LaunchDarkly-<agent-space-id>, and reuses only the server already linked to that space.Reuse and replace behavior is space-scoped. Reuse warns when other spaces share the same server and token.
--replace-mcp-tokenon a shared server registers a new server for this space and disconnects the old link only (other spaces keep the old server); on an exclusive server it deregisters and replaces in place. Rollback paths handle failed disconnects, unused name collisions, and multi-server spaces.User-facing copy and flags (
setuphelp,--replace-mcp-token,--mcp-service-id,--mcp-endpoint) and plan text now describe per-space registration instead of global endpoint lookup. Tests were updated and expanded for the new flows; the old “reconnect all spaces after replace” behavior was removed.Reviewed by Cursor Bugbot for commit 7cb34f5. Bugbot is set up for automated code reviews on this repo. Configure here.